package com.wcy.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wcy.annotation.aop.PreAuth;
import com.wcy.entity.LearningResource;
import com.wcy.entity.ResourceCategory;
import com.wcy.entity.queryVo.QueryConvertor;
import com.wcy.entity.queryVo.RawQueryCondition;
import com.wcy.entity.userVo.UserFiltered;
import com.wcy.service.ILearningResourceService;
import com.wcy.service.IResourceTagMappingService;
import com.wcy.util.JwtTokenUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/learningResource")
public class LearningResourceController {

    @Resource
    private ILearningResourceService learningResourceService;
    @Resource
    private IResourceTagMappingService resourceTagMappingService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;

//    @PreAuth(any={"RESOURCE:QUERY","AUTHENTICATION"})
    @GetMapping("/page")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Page<LearningResource>> getPage(@RequestParam(defaultValue = "1") int pageNum,
                                                          @RequestParam(defaultValue = "10") int pageSize,
                                                          HttpServletRequest request) {
        String queryData = request.getHeader("X-Query-Data");
        QueryWrapper<LearningResource> wrapper = new QueryConvertor<LearningResource>(queryData).convert(true);
        Page<LearningResource> page = learningResourceService.page(new Page<>(pageNum, pageSize),wrapper);
        return ResponseEntity.ok(page);
    }

    @PreAuth("RESOURCE:QUERY")
    @GetMapping("/list")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<List<LearningResource>> getList(HttpServletRequest request) {
        String queryData = request.getHeader("X-Query-Data");
        QueryWrapper<LearningResource> wrapper = new QueryConvertor<LearningResource>(queryData).convert(true);
        List<LearningResource> list = learningResourceService.list(wrapper);
        return ResponseEntity.ok(list);
    }

//    @PreAuth("RESOURCE:QUERY")
    @GetMapping("/{id}")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<LearningResource> get(@PathVariable Integer id) {
        LearningResource learningResource = learningResourceService.getById(id);
        return ResponseEntity.ok(learningResource);
    }

    @PreAuth("RESOURCE:ADD")
    @Transactional
    @PostMapping("/add")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> add(@RequestBody LearningResource learningResource) {
        System.out.println(learningResource);
        learningResource.setCreatedAt(LocalDateTime.now());
        learningResource.setUpdatedAt(LocalDateTime.now());
        resourceTagMappingService.replaceResourceTagMapping(learningResource);
        learningResourceService.save(learningResource);
        return ResponseEntity.ok().build();
    }

    @PreAuth("RESOURCE:ALTER")
    @Transactional
    @PutMapping("/update")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> update(@RequestBody LearningResource learningResource) {
        learningResource.setUpdatedAt(LocalDateTime.now());
        resourceTagMappingService.replaceResourceTagMapping(learningResource);
        learningResourceService.updateById(learningResource);
        return ResponseEntity.ok().build();
    }

    @PreAuth("RESOURCE:DELETE")
    @DeleteMapping("/delete/{id}")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> delete(@PathVariable Integer id) {
        learningResourceService.removeById(id);
        return ResponseEntity.ok().build();
    }

    @PreAuth("AUTHOR:RESOURCE:QUERY")
    @GetMapping("user/page")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Page<LearningResource>> getPageAuthor(@RequestParam(defaultValue = "1") int pageNum,
                                                          @RequestParam(defaultValue = "10") int pageSize,
                                                          HttpServletRequest request) {
        Integer userId = jwtTokenUtil.getUserIdFromToken(jwtTokenUtil.getToken(request));
        String queryData = request.getHeader("X-Query-Data");
        QueryWrapper<LearningResource> wrapper = new QueryConvertor<LearningResource>(queryData, false).convert(true);
        wrapper.eq("author_id",userId);
        Page<LearningResource> page = learningResourceService.page(new Page<>(pageNum, pageSize),wrapper);
        return ResponseEntity.ok(page);
    }

    @PreAuth("AUTHOR:RESOURCE:ALTER")
    @Transactional
    @PutMapping("user/update")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> updateByAuthor(@RequestBody LearningResource learningResource,HttpServletRequest request) {
        Integer userId = jwtTokenUtil.getUserIdFromToken(jwtTokenUtil.getToken(request));
        learningResource.setAuthorId(userId);
        learningResource.setUpdatedAt(LocalDateTime.now());
        resourceTagMappingService.replaceResourceTagMapping(learningResource);
        learningResourceService.updateById(learningResource);
        return ResponseEntity.ok().build();
    }

    @PreAuth("AUTHOR:RESOURCE:DELETE")
    @DeleteMapping("user/delete/{id}")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> deleteByAuthor(@PathVariable Integer id,HttpServletRequest request) {
        Integer userId = jwtTokenUtil.getUserIdFromToken(jwtTokenUtil.getToken(request));
        if (!learningResourceService.getById(id).getAuthorId().equals(userId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        learningResourceService.removeById(id);
        return ResponseEntity.ok().build();
    }

    @PreAuth("AUTHOR:RESOURCE:ADD")
    @PostMapping("user/add")
    @SentinelResource(value = "#root.targetClass + '.' + #root.methodName")
    public ResponseEntity<Void> addByAuthor(@RequestBody LearningResource learningResource,HttpServletRequest request) {
        Integer userId = jwtTokenUtil.getUserIdFromToken(jwtTokenUtil.getToken(request));
        learningResource.setAuthorId(userId);
        learningResource.setCreatedAt(LocalDateTime.now());
        learningResource.setUpdatedAt(LocalDateTime.now());
        learningResourceService.save(learningResource);
        return ResponseEntity.ok().build();
    }

    @GetMapping("getByAuthor/{id}")
    public ResponseEntity<List<LearningResource>> getByAuthor(@PathVariable("id") Integer id){
        assert id != null&&id>0;
        List<LearningResource> list = learningResourceService.list(new QueryWrapper<LearningResource>().eq("author_id", id));
        System.out.println("id:"+id+" "+list);
        return ResponseEntity.ok(list);
    }

    @PostMapping("/listByIds")
    public ResponseEntity<List<LearningResource>> getListByIds(@RequestBody List<Integer> ids){
        assert ids != null;
        return ResponseEntity.ok(learningResourceService.listByIds(ids));
    }
}